home *** CD-ROM | disk | FTP | other *** search
/ Java Developer's Companion / Java Developer's Companion.iso / documentation / jsdk / Counter.jav < prev    next >
Encoding:
Text File  |  1997-08-17  |  9.3 KB  |  300 lines

  1. /*
  2.  * @(#)Counter.java    1.42 97/05/22
  3.  * 
  4.  * Copyright (c) 1996-1997 Sun Microsystems, Inc. All Rights Reserved.
  5.  * 
  6.  * This software is the confidential and proprietary information of Sun
  7.  * Microsystems, Inc. ("Confidential Information").  You shall not
  8.  * disclose such Confidential Information and shall use it only in
  9.  * accordance with the terms of the license agreement you entered into
  10.  * with Sun.
  11.  * 
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  13.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  14.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  15.  * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
  16.  * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
  17.  * THIS SOFTWARE OR ITS DERIVATIVES.
  18.  * 
  19.  * CopyrightVersion 1.0
  20.  */
  21. import java.io.*;
  22. import java.util.*;
  23.  
  24. import javax.servlet.*;
  25. import javax.servlet.http.*;
  26.  
  27. import sun.servlet.http.Cookie;
  28.  
  29.  
  30. /**
  31.  * Simple servlet to demonstrate the "Cookie" API.  It uses a cookie to
  32.  * serve as a counter that increments each time this web page is visited
  33.  * during a user session.  That counter, along with some other data, is
  34.  * shown on an HTML page dynamically generated by this servlet.
  35.  *
  36.  * <P> Of course, other kinds of data can be stored using cookies.  You
  37.  * should look at the privacy and security guidelines in RFC 2109 before
  38.  * you start to use cookies, and be clear to your customers what value
  39.  * your cookies are providing to them.
  40.  *
  41.  * @version 1.42
  42.  * @author  David Brownell
  43.  * @author  Pavani Diwanji
  44.  */
  45. public
  46. class Counter extends HttpServlet {
  47.  
  48.     //
  49.     // Name of the main cookie saved by this servlet.
  50.     //
  51.     private static final String    counterName = "counter";
  52.  
  53.     //
  54.     // Default initial value of session cookies maintained by counter
  55.     // servlets.  May be overriden by an instance's init parameter.
  56.     //
  57.     static final int        defaultInitialValue = 10;
  58.  
  59.     //
  60.     // Actual initial value used by this servlet instance.  There could
  61.     // be several such instances, for different parts of the web site's
  62.     // URL namespace, with different initial values.
  63.     //
  64.     // User agents maintain "live" counter values in cookies which are
  65.     // presented with requests, and the servlet increments such values
  66.     // in its responses.
  67.     //
  68.     private int            initialValue;
  69.  
  70.  
  71.  
  72.     /**
  73.      * Initializes the servlet.  Session counters normally start at ten,
  74.      * but that may be overridden by providing an initialization parameter
  75.      * named "initial" with a value which is a decimal number.  This lets
  76.      * different "counter" servlets have different initial values, as well
  77.      * as letting different user sessions have different actual values.
  78.      */
  79.     public void init(ServletConfig conf) throws ServletException {
  80.     String        s;
  81.  
  82.     super.init(conf);
  83.  
  84.     if ((s = getInitParameter ("initial")) == null)
  85.         initialValue = defaultInitialValue;
  86.     else {
  87.         try {
  88.         initialValue = Integer.parseInt (s);
  89.         } catch (NumberFormatException e) {
  90.         initialValue = defaultInitialValue;
  91.         log ("** Non-numeric format for 'initial' parameter:  " + s);
  92.         }
  93.     }
  94.     }
  95.  
  96.  
  97.     /**
  98.      * Handles a request.  It does this by updating a per-request "counter"
  99.      * cookie from the request, and storing it via the response.  Output of 
  100.      * the servlet is a simple web page showing the original value of the
  101.      * session's counter, and some other data.
  102.      */
  103.     protected void doGet (HttpServletRequest req, HttpServletResponse res)
  104.     throws ServletException, IOException
  105.     {
  106.     int            counter = initialValue;
  107.     Cookie            cookies [], c = null;
  108.     boolean            hadCookies = false, hadCounter = false;
  109.  
  110.     //
  111.     // We do all the cookie work before we start writing output,
  112.     // since once we start writing data the headers (with or
  113.     // without cookies) can get flushed at any time.
  114.     //
  115.     if ((cookies = Cookie.getCookies (req)) != null) {
  116.         hadCookies = true;
  117.  
  118.         for (int i = 0; i < cookies.length; i++) {
  119.         if (cookies [i].getName ().equals (counterName)) {
  120.             try {
  121.  
  122.             // clone this cookie to keep using the browser's
  123.             // version of the cookie protocol
  124.  
  125.             c = (Cookie) cookies [i].clone ();
  126.             counter = Integer.parseInt (c.getValue ());
  127.             c.setValue (Integer.toString (counter + 1));
  128.             hadCounter = true;
  129.             
  130.             } catch (NumberFormatException e) {
  131.             // should never happen ...
  132.             c = null;
  133.             }
  134.             break;
  135.         }
  136.         }
  137.     }
  138.  
  139.     //
  140.     // Always save a "counter" cookie, taking care to set the
  141.     // attributes that weren't settable by cloning the original.
  142.     //
  143.     if (c == null)
  144.         c = new Cookie (counterName, Integer.toString (counter));
  145.     c.setComment ("Supports Cookie Counter Demo Servlet");
  146.     // c.setMaxAge (2 * 24 * 60 * 60);        // 2 days
  147.     // c.setPath ("/");
  148.     c.saveCookie (res);
  149.  
  150.     if (false) {
  151.         // add a new cookie, discarded on browser exit, to see
  152.         // how multiple cookies are dealt with
  153.         c = new Cookie (
  154.         "gensym-" + (System.currentTimeMillis () & 0x0ff),
  155.         new Date().toString ());
  156.         c.setComment ("Show multi-cookie support");
  157.         c.saveCookie (res);
  158.     }
  159.  
  160.  
  161.  
  162.     //
  163.     // TRY THIS:
  164.     //
  165.     // (A) Design a simple form for letting people create new cookies.
  166.     // Generate that form in the HTML below.  Use the POST action, and
  167.     // create the new cookie before generating output below.
  168.     //
  169.     // (B) Do something similar for letting users delete one or more
  170.     // of the cookies reported by the user agent ... including the
  171.     // counter itself, as one way to reinitialize a session!
  172.     //
  173.     // (C) Offer form controls over cookies' paths and maximum ages.
  174.     //
  175.     // (D) Experiment to see how different web browsers handle version
  176.     // zero cookies.  Which features are handled inconsistently?
  177.     //
  178.     // (E) See how this page reacts to HTTP's "HEAD" methods.
  179.     //
  180.     // (F) Normally, pages used to set cookies will not be cached.
  181.     // This will probably be true of most dynamically generated web
  182.     // content.  Are there other pages in your website which should
  183.     // not be widely cached by proxies and browsers?  Why?
  184.     //
  185.  
  186.  
  187.  
  188.     //
  189.     // Generate the response message ... an HTML page that shows all
  190.     // cookies, their values, and any attributes, plus some random
  191.     // data about the session that may be interesting.  We buffer the
  192.     // whole response so that HTTP keepalive can be used.
  193.     //
  194.     ByteArrayOutputStream    bytes;
  195.     PrintStream        out;
  196.  
  197.     bytes = new ByteArrayOutputStream (4096);
  198.     out = new PrintStream (bytes);
  199.  
  200.     out.println ("<HTML><HEAD>");
  201.     out.println ("<TITLE>Cookie Counter</TITLE>");
  202.     out.println ("</HEAD><BODY BGCOLOR=#eeeeff>");
  203.     out.println ("<CENTER><H1>Cookie Counter</H1></CENTER>");
  204.  
  205.     if (hadCounter) {
  206.         out.println ("<CENTER>");
  207.         out.println ("<P> <em><b>Your session's counter was ");
  208.         out.println (counter);
  209.         out.println (" before you visited this page.</b></em>");
  210.         out.println ("<P> The counter has been incremented.");
  211.         out.println ("</CENTER>");
  212.     } else {
  213.         out.println ("<P> You presented no session cookie.  A new");
  214.         out.println ("cookie was created, with an initial counter");
  215.         out.println ("holding the value " + counter + ".");
  216.     }
  217.  
  218.  
  219.     if (hadCookies) {
  220.         out.println ("<P> You presented these cookies: <OL>");
  221.         for (int i = 0; i < cookies.length; i++) {
  222.         String    temp;
  223.  
  224.         out.println ("<LI> Name = ");
  225.         out.println (cookies [i].getName ());
  226.         out.println (", Value = ");
  227.         out.println (cookies [i].getValue ());
  228.  
  229.         //
  230.         // IETF standard cookies expose these attributes, but
  231.         // the original (and still most common) style cookies
  232.         // hide this data on the client side.
  233.         //
  234.         if ((temp = cookies [i].getDomain ()) != null) {
  235.             out.println (", Domain = ");
  236.             out.println (cookies [i].getDomain ());
  237.         }
  238.         if ((temp = cookies [i].getPath ()) != null) {
  239.             out.println (", Path = ");
  240.             out.println (cookies [i].getPath ());
  241.         }
  242.         }
  243.         out.println ("</OL>");
  244.     }
  245.  
  246.  
  247.     out.println ("<P> Watch the value of the counter change as you");
  248.     out.println ("reload this page!  The counter is updated by the");
  249.     out.println ("servlet which dynamically generates this web page.");
  250.  
  251.     out.println ("<P> Try comparing how different browsers work with");
  252.     out.println ("cookies set using these two URLs on this server:  ");
  253.     out.println ("<a href=/counter.html>/counter.html</a>, and");
  254.     out.println ("<a href=/servlet/Counter>/servlet/Counter</a>.");
  255.     out.println ("These URLs refer to different 'counter' servlets,");
  256.     out.println ("which initialize their counts to different values.");
  257.  
  258.  
  259.     String temp = req.getHeader ("User-Agent");
  260.     out.println ("<P> Your browser is <em>"
  261.         + ((temp != null) ? temp : "not known!") + "</em>.");
  262.  
  263.     // XXX
  264.     // This time printing crashes IIS!!!!!
  265.  
  266.     /*
  267.     out.println ("<P>The cookie server's time is now <em>"
  268.         + new Date () + ".</em>");
  269.         */
  270.  
  271.     out.println ("</BODY></HTML>");
  272.     out.flush ();
  273.  
  274.  
  275.     //
  276.     // Now that we've buffered up the entire message:  write all our
  277.     // header fields, then the body.  We buffered it up so we can set
  278.     // content length ... ensuring we can use connection keep-alive,
  279.     // for the best networking performance.
  280.     //
  281.     // With HTTP/1.1 clients guaranteed, we could set the headers
  282.     // and just write to the output stream (using chunked encoding)
  283.     // with no worries about preventing keep-alive.
  284.     //
  285.  
  286.     res.setContentType("text/html");    // ;charset=us-ascii
  287.     res.setContentLength (bytes.size ());
  288.     // ... Last-Modified:  right now!
  289.  
  290.     bytes.writeTo (res.getOutputStream ());
  291.     }
  292.  
  293.     /**
  294.      * Describes what this servlet does.
  295.      */
  296.     public String getServletInfo() {
  297.     return "Demonstrates the 'Cookie' API for user sessions";
  298.     }
  299. }
  300.